﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;

using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using System.Security.Cryptography.X509Certificates;
using System.IO;

using HostPc;

namespace HostPc
{
    namespace AWSIOTCoreSDK
    {
        /**
         * MqttContactAwsIOT_Adapter处理与亚马逊云通信相关事务。*/
        class Adapter
        {
            public HVGSerial.Controller hvg_controller = null;
            public MqttClient mqtt_client = null;
            public Configuration hostpc_config = null;
            public string client_id = Application.GetClientID();
            public DateTime last_pub_time = DateTime.Now;

            /**
             * MqttContactAwsIOT_Adapter()构造函数**/
            public Adapter(ref Configuration __hostpc_config)
            {
                // 设置证书并连接
                hostpc_config = __hostpc_config;
                while (true)
                {
                    try
                    {
                        // 设置证书并连接
                        var ca_cert = X509Certificate.CreateFromCertFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, hostpc_config.path_AmazonRootCA1));
                        var client_cert = new X509Certificate2(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, hostpc_config.path_certificate), "");
                        mqtt_client = new MqttClient(hostpc_config.awsiot_endpoint, hostpc_config.awsiot_broker_port, true, ca_cert, client_cert, MqttSslProtocols.TLSv1_2);
                        break;
                    }
                    catch
                    {
                        Console.WriteLine("证书配置错误");
                        Thread.Sleep(hostpc_config.reconnect_interval_seconds);
                    }
                } // while()

                // 连接awsiot
                ConnectAwsIotCore();

                // 连接成功之后，设置mqtt话题订阅异步函数
                mqtt_client.MqttMsgPublishReceived += Client_MqttMsgPublishReceived;
                mqtt_client.MqttMsgSubscribed += Client_MqttMsgSubscribed;

            } // MqttContactAwsIOT_Adapter()


            /**
             * 当前host设备连接到AWSIOTCore，并且更新当前当前host设备与awsiotcore的连接状态。*/
            public void ConnectAwsIotCore()
            {
                
                // 不断尝试连接AWSIOTCore，直到连接上
                while (true)
                {
                    try
                    {
                        mqtt_client.Connect(client_id, null, null, false, 1, true, hostpc_config.lastwill_topic, hostpc_config.lastwill_payload, true, 5);
                        Console.WriteLine("尝试连接AWSIOTCore成功！");
                        break;
                    }
                    catch
                    {
                        Console.WriteLine("由于网络或者配置原因，尝试连接AWSIOTCore失败！");
                        Thread.Sleep(hostpc_config.reconnect_interval_seconds);
                    }
                } // while()

                // 更新连接后当前设备的状态
                Publish(hostpc_config.lastwill_topic,hostpc_config.online_payload);
                hostpc_config.remote_last_alive = DateTime.Now;
                Console.WriteLine($"成功连接到 AWSIoT，client ID: {client_id}");

            } // connectAWSIOT()

            
            /**
             * host设备发布数据到awsiotcore。*/
            public void Publish(string topic, string publish_data)
            {
                if (mqtt_client == null || !mqtt_client.IsConnected)
                {
                    Console.WriteLine("没有client对象或者client没有连接\n");
                    ReConnectAWSIOTCore();
                    return;
                }
                mqtt_client.Publish(topic, Encoding.UTF8.GetBytes($"{publish_data}"));
                last_pub_time = DateTime.Now;

            } // Publish()


            /**
             * host设备从awsiotcore订阅特定主题的数据*/
            public void Subscribe(ref string topic)
            {
                // 设置订阅异步处理函数
                if (mqtt_client == null || !mqtt_client.IsConnected)
                {
                    Console.WriteLine("没有client对象或者client没有连接\n");
                    ReConnectAWSIOTCore();
                    return;
                }

                mqtt_client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE });
                Console.WriteLine("成功订阅topic：" + topic);

            } // subscribe()


            /**
             * 处理成功订阅事件。*/
            private static void Client_MqttMsgSubscribed(object sender, MqttMsgSubscribedEventArgs e)
            {
                Console.WriteLine("成功订阅 AWSIoT topic.");

            } // Client_MqttMsgSubscribed()


            /**
             * 处理设备成功收到sub主题的消息。*/
            private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
            {
                // 收到remote端话题发布的消息，说明此时remote端在线，更新remote端状态并重新计时。
                hostpc_config.remote_last_alive = DateTime.Now;

                // 将subscribe收到的数据通过RS232写入HVG。
                if (hvg_controller == null)
                {
                    Console.WriteLine("没有rs232_serial对象，请先实例化之\n");
                }
                else
                {
                    hvg_controller.hvg_adapter.hvg_serial_port.Write(Encoding.UTF8.GetString(e.Message));
                    Console.WriteLine("\n收到并写入HVG topic: " + e.Topic + " , message:" + Encoding.UTF8.GetString(e.Message));
                }

            } // Client_MqttMsgPublishReceived()


            /**
             * 重连AWSIOTCore**/
            public MqttClient ReConnectAWSIOTCore()
            {
                // 取消订阅话题
                if (mqtt_client != null) {
                    string[] unsub_string = { hostpc_config.topic_sub };
                    mqtt_client.Unsubscribe(unsub_string);
                }

                // 尝试重新连接AWSIOTCore
                while (true)
                {
                    if (mqtt_client == null)
                    {
                        Console.WriteLine("MQTT Client 当前没有实例化，正在尝试重连！");
                        ConnectAwsIotCore();
                        Thread.Sleep(hostpc_config.reconnect_interval_seconds);
                    }
                    else
                    {
                        if (!mqtt_client.IsConnected)
                        {
                            Console.WriteLine("AWSIOTCore当前未连接，正在尝试重连");
                            ConnectAwsIotCore();
                            Thread.Sleep(hostpc_config.reconnect_interval_seconds);
                        }
                        else
                        {
                            Console.WriteLine("AWSIOTCore重连成功\n\n");
                            break;
                        }
                    }
                } // while()

                Subscribe(ref hostpc_config.topic_sub);
                return mqtt_client;

            } // ReConnectAWSIOTCore

        } // class Adapter


    } // namespace AWSIOTCoreSDK

} // namespace HostPc
